package com.xiang._03.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

/**
 * 服务端  NIO实现简单通讯
 */
public class NioServerSocket {
    public static void main(String[] args) throws IOException {

        //1.打开服务端通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //2、绑定端口
        serverSocketChannel.bind(new InetSocketAddress(9999));
        //3、通道默认阻塞，设置非阻塞
        serverSocketChannel.configureBlocking(false);
        //4、创建选择器
        Selector selector = Selector.open();
        //5、服务端注册到选择器上，并指定注册监听为OP_ACCEPT 连接事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        //6、检查选择器是否有事件
        while (true){
            //这里为阻塞等待客户端连接： // int select = selector.select(2000);
            selector.select();
            //7、获取事件集合
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()){
                SelectionKey key = iterator.next();
                //8、判断客户端是否连接事件 OP_isACCEPTABLE
                if(key.isAcceptable()){
                    //9、将客户端通道注册到选择器上，指定监听为OP_READ，并将通道设置为非阻塞（select选择器需要轮询每个通道的事件）
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector,SelectionKey.OP_READ);
                }

                //10、判断客户端通道是否为读事件
                if(key.isReadable()){
                    //11、取出客户端通道，读取数据到缓冲区
                    SocketChannel channel = (SocketChannel)key.channel();
                    ByteBuffer allocate = ByteBuffer.allocate(50);
                    int read = channel.read(allocate);
                    //读到数据
                    if(read>0){
                        System.out.println("客户端消息："+new String(allocate.array(), StandardCharsets.UTF_8));
                        //12、给客户端返回数据
                        channel.write(ByteBuffer.wrap("服务端返回消息给你".getBytes(StandardCharsets.UTF_8)));
                        channel.close();
                    }
                }
                //13、从集合中删除对应事件，防止二次处理
                iterator.remove();
            }


        }







    }
}
